#include "tcp_server_port.h"

#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/ioctl.h>
#include <string.h>


#include "zmq_manager.h"

TcpServerPort::TcpServerPort(int maxTxFifoSize) : BaseIoPort(maxTxFifoSize)
{

}

TcpServerPort::~TcpServerPort()
{

}

int32_t TcpServerPort::Open(string ip, int32_t port)
{

    mName = ip;
    mParam = port;
    event_fd_def server_fd;

    sockaddr_in local_addr;

    local_addr.sin_addr.s_addr = inet_addr(ip.c_str());
    local_addr.sin_port = htons((u_short)port);
    local_addr.sin_family = AF_INET;

    server_fd = socket(PF_INET, SOCK_STREAM | SOCK_CLOEXEC, IPPROTO_TCP);
    if (server_fd < 0) {
        FLOGE("TcpServer fd init fail");
        return -1;
    }

    int socketoptvalue = 1;
    setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&socketoptvalue, sizeof(int));

    if (bind(server_fd, (struct sockaddr*)&local_addr, sizeof(struct sockaddr)) < 0) {
        FLOGE("TcpServer fd bind fail");
        return -2;
    }

    if (listen(server_fd, 1) < 0) {
        FLOGE("listen error");
        return -3;
    }

    mServerFd = server_fd;
    
    return 0;
}

void TcpServerPort::Listen()
{
    unsigned long ul = 1;
    ioctl(mServerFd, FIONBIO, &ul);  //设置为非阻塞模式
    FLOGE("TcpServerPort::Listen() %d  mStopProcessFlag %d",mServerFd ,mStopProcessFlag);
    int addr_len = sizeof(struct sockaddr_in);
    event_fd_def client_fd;
    sockaddr_in remote_addr;
    while (!mStopProcessFlag) {
        client_fd = accept(mServerFd, (struct sockaddr*)&remote_addr, (socklen_t*)&addr_len);
        if (client_fd < 0) {
            Sleep(100);
            continue;
        }
        mHandle = client_fd;
        mIsOpened = true;
        mOpenedClientPortListMutex.lock();
        mOpenedClientPortList.push_back(this);
        mOpenedClientPortListMutex.unlock();
        break;
    }
}

void TcpServerPort::Start()
{
    mStopProcessFlag = false;
    mPortProcessThread = thread([this]() {
        SetThreadName("baseio_port");
        Listen();
        while (!mStopProcessFlag) {
            if (!BaseIoPort::ProcessLoop())
                this_thread::sleep_for(chrono::milliseconds(100));
        }
    });
}

int32_t TcpServerPort::Close()
{
    if (mIsOpened) {
        mIsOpened = false;
        CLOSE_SOCKET((event_fd_def)mHandle);
        mHandle = 0;
    }
    CLOSE_SOCKET(mServerFd);
    mServerFd = 0;
    mOpenedClientPortListMutex.lock();
    mOpenedClientPortList.remove(this);
    mOpenedClientPortListMutex.unlock();
    return 0;
}